from datetime import timedelta
from django.db import transaction  # 新增事务支持
from django.utils import timezone
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from book import models, ser

# 常量定义（新增）
class BookStatus:
    AVAILABLE = '1'  # 可借阅
    BORROWED = '2'   # 已借出
    ARCHIVED = '3'   # 已归档

class BookLookView(APIView):
    # ... 原有get和post方法保持不变 ...

    # 书籍修改（增强版）
    def put(self, request):
        """
        修改书籍信息（原子操作）
        安全措施：
        1. 使用事务保证数据一致性
        2. 数据副本避免原始数据篡改
        3. 字段白名单验证
        """
        with transaction.atomic():  # 添加事务支持
            data = request.data.copy()
            book_id = data.get('id')
            
            if not book_id:
                return Response({'msg': '缺少书籍ID', 'code': status.HTTP_400_BAD_REQUEST}, status=status.HTTP_400_BAD_REQUEST)
            
            try:
                # 使用select_for_update锁定记录
                book = models.BookModel.objects.select_for_update().get(id=book_id)
                data.pop('id', None)  # 移除ID防止篡改
                
                # 字段白名单（根据模型需要调整）
                allowed_fields = {'title', 'author', 'publisher', 'number', 'status'}
                extra_fields = set(data.keys()) - allowed_fields
                if extra_fields:
                    return Response({'msg': f'非法字段: {",".join(extra_fields)}', 'code': status.HTTP_400_BAD_REQUEST}, 
                                  status=status.HTTP_400_BAD_REQUEST)
                
                serializer = ser.BookSer(book, data=data, partial=True)
                if serializer.is_valid():
                    serializer.save()
                    return Response({'msg': '修改成功', 'code': status.HTTP_200_OK})
                return Response({'msg': serializer.errors, 'code': status.HTTP_400_BAD_REQUEST}, 
                              status=status.HTTP_400_BAD_REQUEST)
            except models.BookModel.DoesNotExist:
                return Response({'msg': '书籍不存在', 'code': status.HTTP_404_NOT_FOUND}, 
                              status=status.HTTP_404_NOT_FOUND)

    # 书籍删除（安全增强版）
    def delete(self, request):
        """
        安全删除逻辑：
        1. 参数校验
        2. 软删除支持
        3. 事务操作
        """
        book_id = request.GET.get('id')
        if not book_id:
            return Response({'msg': '缺少书籍ID', 'code': status.HTTP_400_BAD_REQUEST}, 
                          status=status.HTTP_400_BAD_REQUEST)
        
        try:
            with transaction.atomic():
                # 使用select_for_update锁定记录
                book = models.BookModel.objects.select_for_update().get(id=book_id)
                
                # 检查是否有未归还记录
                if models.BookRecordModel.objects.filter(book=book, is_return=False).exists():
                    return Response({'msg': '存在未归还记录，无法删除', 'code': status.HTTP_409_CONFLICT},
                                  status=status.HTTP_409_CONFLICT)
                
                # 执行软删除（需要模型支持is_deleted字段）
                book.is_deleted = True  # 假设模型有is_deleted字段
                book.status = BookStatus.ARCHIVED
                book.save()
                return Response({'msg': '删除成功', 'code': status.HTTP_200_OK})
                
        except models.BookModel.DoesNotExist:
            return Response({'msg': '书籍不存在', 'code': status.HTTP_404_NOT_FOUND}, 
                          status=status.HTTP_404_NOT_FOUND)


class BorrowBookView(APIView):
    @transaction.atomic  # 添加事务装饰器
    def post(self, request):
        """
        借书操作增强版：
        1. 库存校验原子操作
        2. 并发控制
        3. 输入验证
        """
        try:
            book_id = request.data.get('id')
            reader = request.data.get('reader')
            number = request.data.get('number')
            
            # 输入验证
            if not all([book_id, reader, number]):
                return Response({'msg': '缺少必要参数', 'code': status.HTTP_400_BAD_REQUEST},
                              status=status.HTTP_400_BAD_REQUEST)
            
            try:
                number = int(number)
                if number <= 0:
                    raise ValueError
            except ValueError:
                return Response({'msg': '借阅数量必须为正整数', 'code': status.HTTP_400_BAD_REQUEST},
                              status=status.HTTP_400_BAD_REQUEST)
            
            # 使用select_for_update锁定记录
            book_obj = models.BookModel.objects.select_for_update().get(id=book_id)
            
            if book_obj.status != BookStatus.AVAILABLE:
                return Response({'msg':'书籍不可借阅','code':status.HTTP_403_FORBIDDEN},
                              status=status.HTTP_403_FORBIDDEN)
                
            if book_obj.number < number:
                return Response({'msg':f'当前库存不足，剩余{book_obj.number}本','code':status.HTTP_400_BAD_REQUEST},
                              status=status.HTTP_400_BAD_REQUEST)
            
            # 更新库存
            book_obj.number -= number
            if book_obj.number == 0:
                book_obj.status = BookStatus.BORROWED
            book_obj.save()
            
            # 创建借阅记录
            models.BookRecordModel.objects.create(
                book=book_obj,
                reader=reader,
                return_date=timezone.now().date() + timedelta(days=30),
                number=number
            )
            
            return Response({'msg':'借阅成功','code': status.HTTP_200_OK})
            
        except models.BookModel.DoesNotExist:
            return Response({'msg':'书籍不存在','code':status.HTTP_404_NOT_FOUND},
                          status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'msg': f'系统错误: {str(e)}', 'code': status.HTTP_500_INTERNAL_SERVER_ERROR},
                          status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class ReturnBookView(APIView):
    @transaction.atomic
    def post(self, request):
        """
        还书操作增强版：
        1. 双重校验机制
        2. 状态自动恢复
        3. 异常恢复能力
        """
        try:
            book_id = request.data.get('id')
            reader = request.data.get('reader')
            
            # 获取借阅记录（悲观锁）
            record = models.BookRecordModel.objects.select_for_update().filter(
                book_id=book_id,
                reader=reader,
                is_return=False
            ).first()
            
            if not record:
                return Response({'msg':'未找到有效借阅记录','code':status.HTTP_404_NOT_FOUND},
                              status=status.HTTP_404_NOT_FOUND)
            
            # 获取书籍对象（悲观锁）
            book = models.BookModel.objects.select_for_update().get(id=book_id)
            
            # 更新记录
            record.is_return = True
            record.actual_return_date = timezone.now().date()  # 新增实际归还日期
            record.save()
            
            # 恢复库存
            book.number += record.number
            # 自动恢复状态为可借阅
            if book.status == BookStatus.BORROWED and book.number > 0:
                book.status = BookStatus.AVAILABLE
            book.save()
            
            return Response({'msg':'还书成功','code':status.HTTP_200_OK})
            
        except models.BookModel.DoesNotExist:
            return Response({'msg':'书籍不存在','code':status.HTTP_404_NOT_FOUND},
                          status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'msg': f'系统错误: {str(e)}', 'code': status.HTTP_500_INTERNAL_SERVER_ERROR},
                          status=status.HTTP_500_INTERNAL_SERVER_ERROR)
